# @Time : 2024-10-28 14:26
# @Author : Fioman 
# @Phone : 13149920693
"""
ORM(对象关系映射)
模型类: 模型类表示数据库中的一张表,每个模型类的字段表示表中的一列.
元类: 使用元类在定义模型类时,将字段映射为表字段,并记录表名和字段信息.
字段类: 字段类表示数据库中的每一列(入IntegerField,CharField)
数据库操作: 实现基本的增删查改操作
"""
import numbers


class Field:
    pass


class IntField(Field):
    def __init__(self, dbColumn, minVal=None, maxVal=None):
        self.dbColumn = dbColumn
        self._value = None
        self.minVal = minVal
        self.maxVal = maxVal
        if not isinstance(minVal, numbers.Number):
            raise ValueError("minVal must be an integer")
        if not isinstance(maxVal, numbers.Number):
            raise ValueError("maxVal must be an integer")
        if minVal < 0:
            raise ValueError("minVal must be non-negative")
        if maxVal < 0:
            raise ValueError("maxVal must be non-negative")
        if minVal > maxVal:
            raise ValueError("minVal must be less than maxVal")

    def __get__(self, instance, owner):
        return self._value

    def __set__(self, instance, value):
        if not isinstance(value, numbers.Integral):
            raise ValueError("int value need,but you give type {}".format(type(value)))
        if value < 0:
            raise ValueError("positive value need")
        if value > self.maxVal or value < self.minVal:
            raise ValueError("value must between {} and {}".format(self.minVal, self.maxVal))
        self._value = value


class CharField(Field):
    def __init__(self, dbColumn, maxLen=None):
        self.dbColumn = dbColumn
        self._value = None
        self.maxLen = maxLen
        if maxLen is None:
            raise ValueError("you must spcify maxLen for charfield")

    def __get__(self, instance, owner):
        return self._value

    def __set__(self, instance, value):
        if not isinstance(value, str):
            raise ValueError("str value need,but you give type {}".format(type(value)))
        if len(value) > self.maxLen:
            raise ValueError("字符串长度超过限制, 最大长度为: {}".format(self.maxLen))
        self._value = value


class ModelMetaClass(type):
    def __new__(cls, name, bases, attrs, **kwargs):
        if name == "BaseModel":
            return super().__new__(cls, name, bases, attrs, **kwargs)
        fields = {}
        print(attrs)
        for key, value in attrs.items():
            if isinstance(value, Field):
                fields[key] = value

        attrMeta = attrs.get("Meta", None)
        _meta = {}
        dbTable = name.lower()
        if attrMeta is not None:
            table = getattr(attrMeta, "db_table", None)
            if table is not None:
                dbTable = table
        _meta["dbTable"] = dbTable
        attrs["_meta"] = _meta
        attrs["fields"] = fields
        del attrs["Meta"]
        return super().__new__(cls, name, bases, attrs, **kwargs)


class BaseModel(metaclass=ModelMetaClass):
    def __init__(self, *args, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)
        return super().__init__()

    def save(self):
        fields = []
        values = []
        for attrName, attrObj in self.fields.items():
            dbColumn = attrObj.dbColumn
            if dbColumn is None:
                dbColumn = attrName.lower()
            fields.append(dbColumn)
            value = getattr(self, attrName)
            values.append(str(value))
        sql = f"insert {self._meta["dbTable"]} ({",".join(fields)}) value ({",".join(values)})"
        print(sql)


class User(BaseModel):
    name = CharField(dbColumn="name", maxLen=10)
    age = IntField(dbColumn="age", minVal=1, maxVal=100)

    class Meta:
        dbTable = "user"


user = User()
user.age = 100
user.name = "Fioman"
user.save()
